package com.jwong.common.entity.vo;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.jwong.common.exception.BaseErrorCode;
import com.jwong.common.exception.BaseException;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.ToString;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.time.Instant;
import java.time.ZonedDateTime;

@ApiModel(description = "rest请求返回的模型，所有rest请求结果都应以该实例的形式返回")
@Getter
@ToString
public class Result<T> {

    public static final String SUCCESSFUL_CODE = "000000";
    public static final String SUCCESSFUL_MSG = "操作成功";

    @ApiModelProperty(value = "处理结构code", required = true)
    private String code;

    @ApiModelProperty(value = "处理结果描述信息")
    private String msg;

    @ApiModelProperty(value = "处理结果生成的时间戳")
    private final Instant time;

    @ApiModelProperty(value = "处理结果数据")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private  T data;

    public Result() {
        this.time = ZonedDateTime.now().toInstant();
    }

    public Result(BaseErrorCode errorCode) {
        this();
        this.code = errorCode.getErrCode();
        this.msg = errorCode.getErrMessage();
    }

    public Result(BaseErrorCode errorCode, @Nullable T data) {
        this(errorCode);
        this.data = data;
    }

    public Result(String code, @Nullable T data) {
        this();
        this.code = code;
        this.data = data;
    }

    private Result(String code, String msg, @Nullable T data) {
        this(code, data);
        this.msg = msg;
    }

    private Result(BaseErrorCode errorCode, String msg, @Nullable T data) {
        this(errorCode, data);
        this.msg = msg;
    }

    /**
     *   构建成功的结果，并返回元数据
     */
    public static <T> Result<T> success(@Nullable T data) {
        return new Result<>(SUCCESSFUL_CODE, SUCCESSFUL_MSG, data);
    }

    /**
     *   构建成功的结果，但数据为空
     */
    public static <T> Result<T> success() {
        return success((T)null);
    }

    /**
     *   构建成功的结果，但数据为空
     */
    public static <T> Result<T> success(String msg) {
        return new Result<>(SUCCESSFUL_CODE, msg, null);
    }

    /**
     *   构建成功的结果，但数据为空
     */
    public static <T> Result<T> success(String code, String msg) {
        return new Result<>(code, msg, null);
    }

     /**
      *   构建失败的结果，未知异常
      */
     public static <T> Result<T> fail() {
        return new Result<>(BaseErrorCode.UnknownAppError);
    }

    public static <T> Result<T> fail(String msg) {
        return new Result<>(BaseErrorCode.UnknownAppError, msg, null);
    }

    /**
     *   构建失败的结果，数据为空
     */
    public static <T> Result<T> fail(@Nonnull BaseException baseException) {
        return fail(baseException, null);
    }

    /**
     *   构建失败的结果，数据不为空
     */
    public static <T> Result<T> fail(@Nonnull BaseException baseException, T data) {
        return fail(baseException.getErrorCode(), data);
    }

    public static <T> Result<T> fail(String code, String msg, @Nullable T data) {
        return new Result<>(code, msg, data);
    }

    /**
     *   构建失败的结果，数据不为空
     */
    public static <T> Result<T> fail(BaseErrorCode errorCode, T data) {
        return new Result<>(errorCode, data);
    }

    /**
     *   构建失败的结果，数据为空
     */
    public static <T> Result<T> fail(BaseErrorCode errorCode) {
        return fail(errorCode, null);
    }

    /**
     *   构建失败的结果，数据不为空， 未知异常
     */
    public static <T> Result<T> fail(T data) {
        return new Result<>(BaseErrorCode.UnknownAppError, data);
    }

    /**
     *  成功
     */
    @JsonIgnore
    public boolean isSuccess() {
        return SUCCESSFUL_CODE.equals(this.code);
    }

    /**
     * 失败
     */
    @JsonIgnore
    public boolean isFail() {
        return !isSuccess();
    }

}
